
	function(config) {
	
		var form  = {};
		
		form.state =  {
			
			submitted: false
			
		};
		
		form.windows  = {};
		form.locker   = new Ext.ux.locker;
		form.observer = new Ext.util.Observable;
		
		form.observer.addEvents({
			
			"close"  : true,
			"init"   : true,
			"reload" : true,
			"submit" : true
			
		});
		
		
		/**
		 * Locker: 
		**/
		
		form.locker = new Ext.ux.locker;
		
		form.observer.on("init", function() {
			
			form.locker.setElement( form.windows.main.getEl() );
			
		});
		
		/**
		 * Monitor:
		 */
		form.monitor = {};
		form.monitor.manager = new Ext.util.TaskRunner();
		
		form.monitor.task_validator = {
			
			run: function() {

				try {
					
					var data = form.getData();					
					
				} catch( e ) {
					
					form.buttons.submit.setHighlight(false);
					form.buttons.submit.disable();
					
					if( typeof(e) != "string" ) {
						throw e; }
					
					return;
					
				}
				
				form.buttons.submit.enable();
				
				if( !Ext.compare( form.state.data, data ) ) {
					
					form.buttons.submit.setHighlight(true);
					
				} else {
					
					form.buttons.submit.setHighlight(false);
					
				}
				
			},
			
			interval: 300
			
		};
		
		form.observer.on("reload", function() {

			form.monitor.manager.start(form.monitor.task_validator);
			
		});
		
		form.observer.on("close", function() {
			
			form.monitor.manager.stopAll();
			
		});
		
		form.init = function() {
			
			form.observer.fireEvent("init");
			
		};
				
		/**
		 * Build execute to object 
		**/
		form.execute_on = panel.widgets.list({
			
			id: "execute_on",
			
			store: {
				
				fields: [
				
					{ name: "eid",   type: "int"    },
					{ name: "etype", type: "string" },
					{ name: "title", type: "string" },
					{ name: "ip",    type: "string" }
				
				]
				
			},
			
			grid: {
				
				disableSelection: true,
				
				title   : "Devices:",
				iconCls : "icon_e_device",
				autoExpandColumn: "title",
				
				columns: [
				
					panel.widgets.chunks.grid.columns.title(),
					
					{
						header: "IP",
						dataIndex: "ip",
						width: 100
					}
				
				]		
									
			},

			search: false,
			selection: false,
			clearable: false
			
		});
		
		/**
		 * Fill window items 
		**/	
		form.execute_on.window_items = [
			form.execute_on.grid
		];
		
		form.execute_on.window_items.push( new Ext.Panel({
			
			border: false,
			region: "north",
			height: 40,
			
			html: [
				"<div class='p_5 b_solid_orange_1 s_te'>",
				"<div class='bg_icon_info_side fnt_size_normal a_center'>",
					"Command will be executed<br>on devices listed below." ,
				"</div>",
				"</div>"
			]
			
		}) );
		
		form.windows.execute_on = new Ext.ux.window.WindowDrawer({
			
			width         : 300,
			resizable     : false,
			animate       : false,
			side          : "w",
			monitorResize : false,
			autoScroll    : true,
			layout        : "border",
			baseCls       : "x-mod-purple x-window",
			
			items: form.execute_on.window_items
			
		});
		
		form.locker.observer.on("locked", function() {
			
			form.windows.execute_on.disable();
			
		});
		
		form.locker.observer.on("unlocked", function() {
			
			form.windows.execute_on.enable();
			
		});
		
		/**
		**/
		form.observer.on("init", function() {		

			form.execute_on.init();
							
		});
		
		/**
		 * Form:
		**/
		
		form.buttons = {};
		
		form.buttons.close = new Ext.Button({
			
			cls       : "x-btn-size-28 x-btn-text-icon",
			iconCls   : "icon_action_cancel",
			text      : "Cancel",
			handler   : function() { form.windows.main.close(); }
			
		});
		
		/**
		 * Assign button 
		**/
		
		form.buttons.submit = new Ext.Button({

			cls     : "w_80 x-btn-size-28 x-btn-text-icon",
			iconCls : "icon_action_apply",
			text    : "Execute",
			disabled: true,
			
			handler: function() {
				
				form.submit();
				
			},
				
			listeners: {
				
				enable: function()  { this.setHighlight(true);  },
				disable: function() { this.setHighlight(false); }
				
			}
			
		});
		
		form.execution = {};
		
		form.execution.fields = {};
		form.execution.fields.vendor_title = Ext.id();
		
		form.execution.fields.command = new Ext.form.ComboBox({
			
			name           : "command",
			editable       : true,
			allowBlank     : false,
			resizable      : false,
			typeAhead      : false,
			queryAnyMatch  : true,
			forceSelection : true,
			selectOnFocus  : true,
			width          : 500,
			triggerAction  : "all",
			mode           : "local",
			emptyText      : "Choose command...",
			displayField   : "description",
			valueField     : "eid",
			
			store: new Ext.data.JsonStore({
				
				fields: [
				
					{ name: "uid",   type: "string" },
					{ name: "eid",   type: "string" },
					{ name: "etype", type: "string" },
					{ name: "description", type: "string" },
					{ name: "command", type: "string" }
				
				]
				
			}),
			
			listeners: {
				
				select: function(me, record) {
					
					form.execution.fields.command_preview.setValue( record.data.command );
					
				}				
			}
			
		});
		
		form.execution.fields.command_preview = new Ext.form.TextArea({
			
			name     : "command_preview",
			width    : 650,
			height   : 400,
			readOnly : true
			
		});
		
		form.execution.panel = new Ext.Panel({
			
			region : "center",
			frame  : false,
			border : false,
			
			layout : "template",
			
			items: [
			
				form.execution.fields.command,
				form.execution.fields.command_preview
			
			],
			
			tpl: [
			
				"<div class='wh_max bg_form panel_widgets_form_area'>",
				"<div class='p_15'>",
					
					"<table class='w_max h_50 mbr_5 b_solid_orange_1 bg_te'>",
					"<tr>",
						"<td class='fnt_size_12pt s_bold a_center p_lr5'>",
						"Vendor: <span id='", form.execution.fields.vendor_title, "'></span> </td>",
					"</tr>",
					"</table>",
					
					"<table border='0' class='w_max p_t10'>",
					"<tr>",
						"<td class='label w_80'>Command:</td>",
						"<td>{command:field}</td>",
					"</tr>",
					"<tr>",
						"<td colspan='2' class='label p_t10'>Command code preview (read-only):</td>",
					"</tr>",
					"<tr>",
						"<td colspan='2' class='p_tb5'>{command_preview:field}</td>",
					"</tr>",
					"</table>",
					
				"</div>",
				"</div>"	
			
			].join("")
			
		});
		
		/**
		 * Main 
		**/
		
		form.windows.main = new Ext.Window({
					
			border     : true,
			iconCls    : "icon_action_run",
			modal      : true,
			resizable  : false,
			title      : "Execute commands",
			layout     : "border",
			width      : 700,
			height     : 650,
			
			plugins: [ form.windows.execute_on ],
			items:   [ form.execution.panel ],
			
			buttonAlign: "center",
			
			buttons: [
				
				form.buttons.submit,
				form.buttons.close
				
			],
			
			listeners: {
				
				close: function() {
					
					if( config.callback instanceof Function ) {
						config.callback(form.state); }
					
				},
				
				show: function() {
					
					form.windows.execute_on.show();
					
					var _pos = form.windows.main.getPosition();	
					
					form.windows.main.setPosition(_pos[0] + 100, _pos[1]);

					if( !form.state.init ) {
						
						form.init();
						form.state.init = true;
						
					}	// if
					
				}
				
			}
			
		});
		
		form.observer.on("init", function() {
			
			form.reload();
			
		});
		
		form.getData = function() {
			
			if( !form.execution.fields.command.isValid() ) {
				throw "Command is not valid"; }
			
			return {
				
				"command_id" : form.execution.fields.command.getValue(),
				"devices"    : config.devices, 
				"vendor_id"  : config.vendor_id
				
			};
			
		};
		
		form.reload = function() {
			
			form.locker.lock("Loading...");
			
			panel.ajax({
				
				_p  : "commands_executor",
				_pa : "get_preexecution_data",
				_rt : "text/json",
				_pd : {
					
					"devices"   : config.devices, 
					"vendor_id" : config.vendor_id
					
				},
				
				onFailure: function() {
					
					form.windows.main.close();
					return false;
					
				},
				
				onComplete: function(r) {
					
					form.locker.unlock();
					
					form.execute_on.loadData(r.devices);
					
					Ext.get( form.execution.fields.vendor_title ).update( r.vendor.title );
					
					form.execution.fields.command.getStore().loadData( r.commands );
					
					try {
						
						form.state.data = form.getData();
						
					} catch(e) {};
					
					form.observer.fireEvent("reload", r);
					
				}
				
			}).request();
			
		};
		
		form.submit = function() {
			
			try {
						
				var data = form.getData();
				
			} catch(e) {
				
				panel.ui.alert.validation_failed(e);
				
				return;
				
			};
			
			var request = panel.ajax({
				
				_p  : "commands_executor",
				_pa : "execute_command",
				_rt : "text/json",
				_pd : data,
				
				onRequest: function() {
					
					form.locker.lock("Executing command...");
					
				},
				
				onFailure: function() {
					
					form.locker.unlock();
					return false;
					
				},
				
				onComplete: function(r) {
					
					form.state.data = data;
					form.state.submitted = true;
					form.observer.fireEvent("submit");
					
					Ext.Msg.show({
					
						title: "Execution log:",
						
						msg: [
							
							"<div class='h_500' style='overflow: auto;'>",
							"<pre>", r.output, "</pre>",
							"</div>"
							
						].join(""),
						
						width   : 500,
						buttons : Ext.Msg.OK,
						icon    : Ext.MessageBox.INFO
						
					});
					
					form.locker.unlock();
					
					
				}
				
			});
			
			Ext.Msg.show({
					
				title: "Confirmation",
				
				msg: [
					
					"<font class='c_red s_bold fnt_size_main'>",
					"Are you sure you want to execute?",
					"</font>"
					
				].join(""),
				
				width   : 400,
				buttons : Ext.Msg.YESNO,
				icon    : Ext.MessageBox.QUESTION,
				fn      : function(a) {
					
					if( a != "yes" ) {
						return; }
					
					request.request();
					
				}
				
			});
			
		};
		
		form.windows.main.show();
		
	}

